<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>First class callable syntax</title>
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-base.css" />
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-medium.css" />

 </head>
 <body class="docs"><div class="navbar navbar-fixed-top">
  <div class="navbar-inner clearfix">
    <ul class="nav" style="width: 100%">
      <li style="float: left;"><a href="functions.arrow.html">« 箭头函数</a></li>
      <li style="float: right;"><a href="language.oop5.html">类与对象 »</a></li>
    </ul>
  </div>
</div>
<div id="breadcrumbs" class="clearfix">
  <ul class="breadcrumbs-container">
    <li><a href="index.html">PHP Manual</a></li>
    <li><a href="language.functions.html">函数</a></li>
    <li>First class callable syntax</li>
  </ul>
</div>
<div id="layout">
  <div id="layout-content"><div id="functions.first_class_callable_syntax" class="sect1">
  <h2 class="title">First class callable syntax</h2>

  <p class="para">
   The first class callable syntax is introduced as of PHP 8.1.0, as a way of creating <a href="functions.anonymous.html" class="link">anonymous functions</a> from <a href="language.types.callable.html" class="link">callable</a>.
   It supersedes existing callable syntax using strings and arrays.
   The advantage of this syntax is that it is accessible to static analysis, and uses the scope at the point where the callable is acquired.
  </p>

  <p class="para">
   <code class="code">CallableExpr(...)</code> syntax is used to create a <span class="classname"><a href="class.closure.html" class="classname">Closure</a></span> object from callable. <code class="code">CallableExpr</code> accepts any expression that can be directly called in the PHP grammar:
   <div class="example" id="example-190">
    <p><strong>示例 #1 Simple first class callable syntax</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">method</span><span style="color: #007700">()&nbsp;{}<br />&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;function&nbsp;</span><span style="color: #0000BB">staticmethod</span><span style="color: #007700">()&nbsp;{}<br />&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">__invoke</span><span style="color: #007700">()&nbsp;{}<br />}<br /></span><span style="color: #0000BB">$obj&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$classStr&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'Foo'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$methodStr&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'method'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$staticmethodStr&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'staticmethod'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$f1&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">strlen</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">$f2&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$obj</span><span style="color: #007700">(...);&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;invokable&nbsp;object<br /></span><span style="color: #0000BB">$f3&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">method</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">$f4&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">$methodStr</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">$f5&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">::</span><span style="color: #0000BB">staticmethod</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">$f6&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$classStr</span><span style="color: #007700">::</span><span style="color: #0000BB">$staticmethodStr</span><span style="color: #007700">(...);<br /></span><span style="color: #FF8000">//&nbsp;traditional&nbsp;callable&nbsp;using&nbsp;string,&nbsp;array<br /></span><span style="color: #0000BB">$f7&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'strlen'</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">$f8&nbsp;</span><span style="color: #007700">=&nbsp;[</span><span style="color: #0000BB">$obj</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'method'</span><span style="color: #007700">](...);<br /></span><span style="color: #0000BB">$f9&nbsp;</span><span style="color: #007700">=&nbsp;[</span><span style="color: #0000BB">Foo</span><span style="color: #007700">::class,&nbsp;</span><span style="color: #DD0000">'staticmethod'</span><span style="color: #007700">](...);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

   </div>
  </p>

  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <p class="para">
    The <code class="code">...</code> is part of the syntax, and not an omission.
   </p>
  </p></blockquote>

  <p class="para">
   <code class="code">CallableExpr(...)</code> has the same semantics as <span class="methodname"><a href="closure.fromcallable.html" class="methodname">Closure::fromCallable()</a></span>.
   That is, unlike callable using strings and arrays, <code class="code">CallableExpr(...)</code> respects the scope at the point where it is created:
   <div class="example" id="example-191">
    <p><strong>示例 #2 Scope comparison of <code class="code">CallableExpr(...)</code> and traditional callable</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">getPrivateMethod</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[</span><span style="color: #0000BB">$this</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'privateMethod'</span><span style="color: #007700">];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;function&nbsp;</span><span style="color: #0000BB">privateMethod</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">__METHOD__</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000BB">$foo&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$privateMethod&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$foo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getPrivateMethod</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$privateMethod</span><span style="color: #007700">();<br /></span><span style="color: #FF8000">//&nbsp;Fatal&nbsp;error:&nbsp;Call&nbsp;to&nbsp;private&nbsp;method&nbsp;Foo::privateMethod()&nbsp;from&nbsp;global&nbsp;scope<br />//&nbsp;This&nbsp;is&nbsp;because&nbsp;call&nbsp;is&nbsp;performed&nbsp;outside&nbsp;from&nbsp;Foo&nbsp;and&nbsp;visibility&nbsp;will&nbsp;be&nbsp;checked&nbsp;from&nbsp;this&nbsp;point.<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo1&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">getPrivateMethod</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;Uses&nbsp;the&nbsp;scope&nbsp;where&nbsp;the&nbsp;callable&nbsp;is&nbsp;acquired.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">return&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">privateMethod</span><span style="color: #007700">(...);&nbsp;</span><span style="color: #FF8000">//&nbsp;identical&nbsp;to&nbsp;Closure::fromCallable([$this,&nbsp;'privateMethod']);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">}<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;function&nbsp;</span><span style="color: #0000BB">privateMethod</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">__METHOD__</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000BB">$foo1&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo1</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$privateMethod&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$foo1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getPrivateMethod</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$privateMethod</span><span style="color: #007700">();&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;Foo1::privateMethod<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

   </div>

  </p>

  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <p class="para">
    Object creation by this syntax (e.g <code class="code">new Foo(...)</code>) is not supported, because <code class="code">new Foo()</code> syntax is not considered a call.
   </p>
  </p></blockquote>

  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <p class="para">
    The first-class callable syntax cannot be combined with the <a href="language.oop5.basic.html#language.oop5.basic.nullsafe" class="link">nullsafe operator</a>. Both of the following result in a compile-time error:
    <div class="example" id="example-192">
     <div class="example-contents">
      <div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br />$obj</span><span style="color: #007700">?-&gt;</span><span style="color: #0000BB">method</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">$obj</span><span style="color: #007700">?-&gt;</span><span style="color: #0000BB">prop</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">method</span><span style="color: #007700">(...);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
     </div>

    </div>
   </p>
  </p></blockquote>
 </div></div></div></body></html>